from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_apscheduler import APScheduler
from config import Config
import redis
import pymysql
import logging
import os

pymysql.install_as_MySQLdb()

db = SQLAlchemy()
migrate = Migrate()
apscheduler = APScheduler()
redis_client = None

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)


def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)

    db.init_app(app)
    migrate.init_app(app, db)

    global redis_client
    redis_client = redis.Redis(
        host=app.config["REDIS_HOST"],
        port=app.config["REDIS_PORT"],
        db=app.config["REDIS_DB"],
    )

    from . import views, views_page
    # models和scheduler模块在当前应用初始化中不需要显式导入
    # 如果后期需要在应用启动时初始化这些模块，请取消下面的注释
    # from . import models, scheduler

    views.init_app(app)
    views_page.init_app(app)

    # 应用照护时间线生成逻辑的修复
    apply_care_timeline_fix()

    # 初始化调度器
    init_scheduler(app)

    return app


def apply_care_timeline_fix():
    """应用照护时间线生成逻辑的修复"""
    import logging

    # 只在应用启动时执行一次
    if hasattr(apply_care_timeline_fix, "executed"):
        return

    logging.info("开始应用照护时间线生成逻辑的修复...")

    try:
        # 导入修复模块
        from .three_shift_fix_care_timeline import apply_fix_to_three_shift

        # 应用修复
        result = apply_fix_to_three_shift()

        if result:
            logging.info("照护时间线生成逻辑的修复应用成功")
        else:
            logging.warning("照护时间线生成逻辑的修复应用失败")
    except Exception as e:
        logging.error(f"应用照护时间线生成逻辑的修复时出错: {str(e)}")

    # 标记为已执行
    apply_care_timeline_fix.executed = True


def migrate_auto_schedule_params():
    """迁移自动排班参数到通用参数

    为了确保向后兼容性，将旧的自动排班专用参数迁移到通用参数
    """
    from config_params import three_shift_params
    import logging

    # 只在应用启动时执行一次
    if hasattr(migrate_auto_schedule_params, "executed"):
        return

    logging.info("开始迁移自动排班参数...")

    # 记录参数变更
    changes = {}

    # 迁移班制模式参数
    if "auto_schedule_shift_mode" in three_shift_params:
        old_value = three_shift_params.get("shift_mode")
        new_value = three_shift_params.pop("auto_schedule_shift_mode")
        if "shift_mode" not in three_shift_params:
            three_shift_params["shift_mode"] = new_value
            changes["shift_mode"] = {"old": old_value, "new": new_value}

    # 迁移时间槽数量参数
    if "auto_schedule_time_slots_per_day" in three_shift_params:
        old_value = three_shift_params.get("time_slots_per_day")
        new_value = three_shift_params.pop("auto_schedule_time_slots_per_day")
        if "time_slots_per_day" not in three_shift_params:
            three_shift_params["time_slots_per_day"] = new_value
            changes["time_slots_per_day"] = {"old": old_value, "new": new_value}

    # 迁移时间间隔参数
    if "auto_schedule_time_interval_minutes" in three_shift_params:
        old_value = three_shift_params.get("time_interval_minutes")
        new_value = three_shift_params.pop("auto_schedule_time_interval_minutes")
        if "time_interval_minutes" not in three_shift_params:
            three_shift_params["time_interval_minutes"] = new_value
            changes["time_interval_minutes"] = {"old": old_value, "new": new_value}

    # 迁移自定义班次参数
    if "auto_schedule_custom_shifts" in three_shift_params:
        old_value = three_shift_params.get("custom_shifts")
        new_value = three_shift_params.pop("auto_schedule_custom_shifts")
        if "custom_shifts" not in three_shift_params:
            three_shift_params["custom_shifts"] = new_value
            changes["custom_shifts"] = {"old": old_value, "new": new_value}

    # 如果有参数变更，记录最后一次更新时间和内容
    if changes:
        from datetime import datetime
        three_shift_params["last_params_update"] = {
            "time": datetime.now().isoformat(),
            "changes": changes,
            "source": "parameter_migration"
        }
        logging.info(f"参数迁移完成，变更: {changes}")
    else:
        logging.info("没有需要迁移的参数")

    # 标记为已执行
    migrate_auto_schedule_params.executed = True


def init_scheduler(app):
    """初始化定时任务调度器

    Args:
        app: Flask应用实例
    """
    from config_params import three_shift_params
    import os

    # 迁移自动排班参数
    migrate_auto_schedule_params()

    # 检查是否启用自动排班
    auto_schedule_enabled = three_shift_params.get("auto_schedule_enabled", False)
    auto_schedule_immediate = three_shift_params.get("auto_schedule_immediate", True)

    # 获取自动排班间隔分钟数
    auto_schedule_minutes = three_shift_params.get("auto_schedule_minutes", 7)

    # 导入自动排班函数
    from .three_shift import auto_schedule

    # 检查是否使用新的自动排班机制
    use_new_scheduler = os.environ.get("USE_NEW_AUTO_SCHEDULER", "1") == "1"

    if use_new_scheduler:
        # 使用新的自动排班机制
        from .auto_scheduler import auto_scheduler

        # 创建一个包装函数，用于执行自动排班
        def scheduled_auto_schedule():
            return auto_schedule()

        # 初始化自动排班调度器
        auto_scheduler.initialize(
            app=app,
            schedule_func=scheduled_auto_schedule,
            interval_minutes=auto_schedule_minutes,
            enabled=auto_schedule_enabled
        )

        # 启动自动排班调度器
        auto_scheduler.start(run_immediately=auto_schedule_immediate)

        logging.info(f"使用新的自动排班机制，间隔 {auto_schedule_minutes} 分钟，{'立即执行' if auto_schedule_immediate else '不立即执行'}")
    else:
        # 使用原有的自动排班机制
        # 配置APScheduler
        apscheduler.init_app(app)
        apscheduler.api_enabled = False  # 禁用API接口

        # 创建一个包装函数，传入app参数
        def scheduled_auto_schedule():
            with app.app_context():
                auto_schedule()

        if auto_schedule_enabled:
            # 添加自动排班任务
            apscheduler.add_job(
                id="auto_schedule_job",
                func=scheduled_auto_schedule,
                trigger="interval",
                minutes=auto_schedule_minutes,
                replace_existing=True,
            )

            # 启动调度器
            apscheduler.start()
            logging.info(f"使用原有的自动排班机制，间隔 {auto_schedule_minutes} 分钟")

            # 如果配置了立即执行，则立即执行一次排班
            if auto_schedule_immediate:
                logging.info("立即执行一次自动排班...")
                scheduled_auto_schedule()
                logging.info("立即执行自动排班完成")
        else:
            logging.info("自动排班功能未启用")
